﻿#include "StringTransform.h"

#ifdef WIN32  
#include "iconv.h"  
#else  
#include "../../../cocos2d/external/iconv/include/iconv.h"
#endif  

#if(CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)  
#pragma comment(lib, "libiconv.lib")  
#endif 

iconv_t g2u_cd;
iconv_t u2g_cd;

//构造函数
StringTransform::StringTransform()
{
	codeConvertInit();
}

//析构函数
StringTransform::~StringTransform()
{
	codeConvertDestroy();
}

void StringTransform::codeConvertInit()
{
	g2u_cd = iconv_open("utf-8", "gbk");
	u2g_cd = iconv_open("gbk", "utf-8");
}

void StringTransform::codeConvertDestroy()
{
	iconv_close(g2u_cd);
	iconv_close(u2g_cd);
}

std::string StringTransform::wstringToString(const std::wstring& ws)
{
	std::string curLocale = setlocale(LC_ALL, NULL);        // curLocale = "C";
	setlocale(LC_ALL, "chs");
	const wchar_t* _Source = ws.c_str();
	size_t _Dsize = 2 * ws.size() + 1;
	char *_Dest = new char[_Dsize];
	memset(_Dest, 0, _Dsize);
	wcstombs(_Dest, _Source, _Dsize);
	static std::string result = _Dest;
	delete[]_Dest;
	setlocale(LC_ALL, curLocale.c_str());
	return result;
}

std::wstring StringTransform::stringToWstring(const std::string& s)
{
	setlocale(LC_ALL, "chs");
	const char* _Source = s.c_str();
	size_t _Dsize = s.size() + 1;
	wchar_t *_Dest = new wchar_t[_Dsize];
	wmemset(_Dest, 0, _Dsize);
	mbstowcs(_Dest, _Source, _Dsize);
	static std::wstring result = _Dest;
	delete[]_Dest;
	setlocale(LC_ALL, "C");
	return result;
}

int StringTransform::unicodeToUTF8(const wchar_t * wstr, string &out_str)
{
	if (!wstr)
		return 1;
	char* str = NULL;
	int size = 0;
	std::string loc = setlocale(LC_ALL, NULL);
	setlocale(LC_ALL, "zh_CN.utf8");
	size = wcstombs(NULL, wstr, 0);
	str = new char[size + 1];
	wcstombs(str, wstr, size);
	str[size] = '\0';
	out_str = str;
	setlocale(LC_ALL, loc.c_str());
	return 0;
}

int StringTransform::utf8ToUnicode(const char* str, wstring &out_wstr)
{
	if (!str)
		return 1;
	wchar_t* wcs = NULL;
	int size = 0;
	string loc = setlocale(LC_ALL, NULL);
	setlocale(LC_ALL, "zh_CN.utf8");
	size = mbstowcs(NULL, str, 0);
	wcs = new wchar_t[size + 1];
	size = mbstowcs(wcs, str, size + 1);
	wcs[size] = 0;
	out_wstr = wcs;
	delete[] wcs;
	setlocale(LC_ALL, loc.c_str());
	return 0;
}

void StringTransform::wstringToUTF8(std::string& dest, const wstring& src)
{
	dest.clear();
	for (size_t i = 0; i < src.size(); i++){
		wchar_t w = src[i];
		if (w <= 0x7f)
			dest.push_back((char)w);
		else if (w <= 0x7ff){
			dest.push_back(0xc0 | ((w >> 6) & 0x1f));
			dest.push_back(0x80 | (w & 0x3f));
		}
		else if (w <= 0xffff){
			dest.push_back(0xe0 | ((w >> 12) & 0x0f));
			dest.push_back(0x80 | ((w >> 6) & 0x3f));
			dest.push_back(0x80 | (w & 0x3f));
		}
		else if (sizeof(wchar_t) > 2 && w <= 0x10ffff){
			dest.push_back(0xf0 | ((w >> 18) & 0x07)); // wchar_t 4-bytes situation
			dest.push_back(0x80 | ((w >> 12) & 0x3f));
			dest.push_back(0x80 | ((w >> 6) & 0x3f));
			dest.push_back(0x80 | (w & 0x3f));
		}
		else
			dest.push_back('?');
	}
}

std::string StringTransform::utf8ToGbk(char src[])
{
	std::string ans;
	int len = strlen(src)*2+1;
	char *dst = (char *)new char[len];
	if(dst == NULL)
		return ans;

	memset(dst, 0, len);
	char *in = src;
	char *out = dst;
	size_t len_in = strlen(src);
	size_t len_out = len;

	if ((iconv_t)-1 == u2g_cd)
	{
		delete[] dst;
		return ans;
	}

	int n = 0;

	const char *temp = src;
	const char **pin = &temp;
	char **pout = &out;
	n = iconv(u2g_cd, pin, &len_in, pout, &len_out);

	if(n<0)
	{

	}
	else
	{
		ans = dst;
	}

	delete [] dst;
	return ans;
}

std::string StringTransform::gbkToUTF8(char src[])
{
	std::string ans;
	int len = strlen(src)*2+1;
	char *dst = (char *)new char[len];
	if(dst == NULL)
		return ans;

	memset(dst, 0, len);
	char *in = src;
	char *out = dst;
	size_t len_in = strlen(src);
	size_t len_out = len;

	if ((iconv_t)-1 == g2u_cd)
	{
		delete[] dst;
		return ans;
	}

	int n = 0;

	const char *temp = src;
	const char **pin = &temp;
	char **pout = &out;

	n = iconv(g2u_cd, pin, &len_in, pout, &len_out);

	if(n<0)
	{

	}
	else
	{
		ans = dst;
	}

	delete [] dst;
	return ans;
}

std::string StringTransform::utf8ToGbk(const char* src)
{
	char* temp = new char[strlen(src)+1];
	memcpy(temp, src, strlen(src)+1);
	std::string strgbk = utf8ToGbk(temp);
	delete [] temp;
	return strgbk;
}

std::string StringTransform::gbkToUTF8(const char* src)
{
	char* temp = new char[strlen(src)+1];
	memcpy(temp, src, strlen(src)+1);
	std::string strgbk = gbkToUTF8(temp);
	delete [] temp;
	return strgbk;
}

bool StringTransform::IsLegitimateChrName(const char* name)
{
	char* tempname = new char[strlen(name)+1];
	memcpy(tempname, name, strlen(name)+1);
	std::string strgbk = utf8ToGbk(tempname);
	delete [] tempname;

	unsigned char ch1,ch2;
	const char *p = strgbk.c_str();
	for( ; *p!='\0'; ++p )
	{
		ch1=*p;
		if( ch1&0x80 )
		{
			ch2=*p;
			if( ! (ch1 >=0x81 && ch1<=0xfe && ch2>=0x40 && ch2<=0xfe && ch2!=0x7f ) )
			{
				return false;
			}
			++p;
		}
		else
		{
			if( !( (ch1>='a' &&  ch1 <='z') ||  (ch1>='A' &&  ch1<='Z') || (ch1>='0' &&  ch1 <='9') ) )
			{
				if(ch1 <= 32 || ch1==33 || ch1==34 || ch1==37 || ch1==39 || ch1==64 || ch1==94 || ch1==127)
				{
					return false;
				}
			}

		}
	}
	return true;
}

bool StringTransform::IsLegitimateAccountName(const char* name)
{
	unsigned char ch1,ch2;
	const char *p = name;
	for( ; *p!='\0'; ++p )
	{
		ch1=*p;

		if( !( (ch1>='a' &&  ch1 <='z') ||  (ch1>='A' &&  ch1<='Z') || (ch1>='0' &&  ch1 <='9') ) )
		{
			return false;
		}
	}
	return true;
}

bool StringTransform::IsAllNum(const char* str)
{
	unsigned char ch1,ch2;
	const char *p = str;
	for( ; *p!='\0'; ++p )
	{
		ch1=*p;

		if( !(ch1>='0' &&  ch1 <='9') )
		{
			return false;
		}
	}
	return true;
}

int StringTransform::code_convert(const char *from_charset, const char *to_charset, const char *inbuf, size_t inlen, char *outbuf, size_t outlen)
{
	iconv_t cd;
	const char *temp = inbuf;
	const char **pin = &temp;
	char **pout = &outbuf;
	memset(outbuf, 0, outlen);
	cd = iconv_open(to_charset, from_charset);
	if (cd == 0)	return -1;

	if (iconv(cd, pin, &inlen, pout, &outlen) == -1)	return -1;
	
	iconv_close(cd);
	return 0;
}

//std::wstring StringTransform::ansiToUnicode(const char* buf)
//{
//#ifdef WIN32
//	int len = ::MultiByteToWideChar(CP_ACP, 0, buf, -1, 0, 0);
//	if (len == 0) return L"";
//
//	std::vector<wchar_t> unicode(len);
//	::MultiByteToWideChar(CP_ACP, 0, buf, -1, &unicode[0], len);
//	return &unicode[0];
//#else
//	return 0;
//#endif
//}

//std::string StringTransform::unicodeToAnsi(const wchar_t* buf)
//{
//#ifdef WIN32
//	int len = ::WideCharToMultiByte(CP_ACP, 0, buf, -1, 0, 0, 0, 0);
//	if (len == 0) return "";
//
//	std::vector<char> utf8(len);
//	::WideCharToMultiByte(CP_ACP, 0, buf, -1, &utf8[0], len, 0, 0);
//
//	return &utf8[0];
//#else
//	return 0;
//#endif
//}

/*GB2312תUTF8*/
std::string StringTransform::GbToUTF8(const char *inbuf)
{
	size_t inlen = strlen(inbuf);
	char * outbuf = new char[inlen * 2 + 2];
	memset(outbuf, 0, sizeof(char)*(inlen * 2 + 2));
	std::string strRet;
	if (code_convert("gb2312", "utf-8", inbuf, inlen, outbuf, inlen * 2 + 2) == 0)
	{
		strRet = outbuf;
	}
	else
	{
		if (code_convert("gb18030", "utf-8", inbuf, inlen, outbuf, inlen * 2 + 2) == 0)
			strRet = outbuf;
	}
	delete[] outbuf;
	return strRet;
}

/*UTF8转GB2312*/
std::string StringTransform::utf8ToGb(const char *inbuf)
{
	size_t inlen = strlen(inbuf);

	char * outbuf = new char[inlen * 2 + 2];

	std::string strRet;

	if (code_convert("utf-8", "gb2312", inbuf, inlen, outbuf, inlen * 2 + 2) == 0)
	{
		strRet = outbuf;
	}
	else
	{
		// e.g：冇
		if (code_convert("utf-8", "gb18030", inbuf, inlen, outbuf, inlen * 2 + 2) == 0)
			strRet = outbuf;
	}

	delete[] outbuf;

	return strRet;
}